﻿#include "IDataRepository.h"

IDataRepository::IDataRepository()
{
}

IDataRepository::~IDataRepository()
{
}

//// 增加数据，包括【键】和【值】
//int IDataRepository::addData(const MSG_KEY msgKey, const MSG_VALUE msgValue)
//{
//
//	return 0;
//}
//
//// 根据【键】获得【值】
//int  IDataRepository::getMsgValue(const MSG_KEY msgKey, MSG_VALUE& msgValue)
//{
//
//	return 0;
//}

/*
制作 Key , 注意：
	iMainCode 最多3个字节，必需小于 0x00FFFFFF/2 即 16777215/2=8388607 ,除以2是要考虑负数范围
	iSubCode  最多3个字节，必需小于 0x00FFFFFF/2 即 16777215/2=8388607 ,除以2是要考虑负数范围
	iT3Code最多2个字节，必需小于 0x00FFFF/2 即 32767 ,除以2是要考虑负数范围
*/
int64_t IDataRepository::makeKey(int iMainCode, int iSubCode, int iT3Code)
{
	int64_t v1 = 0;
	int64_t v2 = 0;
	int64_t v3 = 0;

	v1 = iMainCode;
	v1 = v1 & 0x0000000000FFFFFF;		// 清零前5个字节
	v1 = v1 << 40;	// 左移40位，即左移5个字节

	v2 = iSubCode;
	v2 = v2 & 0x0000000000FFFFFF;		// 清零前5个字节
	v2 = v2 << 16;	// 左移16位，即左移2个字节

	v3 = iT3Code;
	v3 = v3 & 0x000000000000FFFF;		// 清零前6个字节

	int64_t  msgKey = v1 + v2 + v3;

	return msgKey;
}

/*
获得 Key ，注意：
	iMainCode 最多3个字节，必需小于 0x00FFFFFF/2 即 16777215/2=8388607 ,除以2是要考虑负数范围
	iSubCode  最多3个字节，必需小于 0x00FFFFFF/2 即 16777215/2=8388607 ,除以2是要考虑负数范围
	iT3Code最多2个字节，必需小于 0x00FFFF/2 即 32767 ,除以2是要考虑负数范围
*/
void IDataRepository::getKey(int64_t msgKey, int& iMainCode, int& iSubCode, int& iT3Code)
{
	int64_t v1 = msgKey;
	int64_t v2 = msgKey;
	int64_t v3 = msgKey;

	v1 = v1 & 0xFFFFFF0000000000;		// 清零后5个字节
	v1 = v1 >> 40;	// 右移40位，即右移5个字节
	iMainCode = v1;

	v2 = v2 & 0x000000FFFFFF0000;		// 清零前3个字节和后3个字节
	v2 = v2 >> 16;	// 右移16位，即右移2个字节
	iSubCode = v2;

	v3 = v3 & 0x000000000000FFFF;		// 清零前6个字节
	iT3Code = v3;
}

/* --------------------------------------------------------------------------
函数说明：向数据仓库写入数据
传入参数：
	iMainCode		主码
	iSubCode		辅助码
	iT3Code			三级码
	pData				要保存的一条记录的数据
	iDataLen			一条记录的数据的长度
返回值：
	成功则返回 0，失败返回错误码
-------------------------------------------------------------------------- */
int IDataRepository::writeToRepository(int iMainCode, int iSubCode, int iT3Code, MSG_VALUE::STATE state, const char*  pData, int iDataLen)
{
	if (!pData)
		return ERR_pData_is_null;

	if (iDataLen<=0)
		return ERR_iDataLen_is_0;

	int64_t  iKey = makeKey(iMainCode, iSubCode, iT3Code);

	std::lock_guard<std::recursive_mutex> guard(_lockRepository);		// 加锁

	MAP_DATA_REPOSITORY_ITER iter = _dataRepository.find(iKey);

	if (iter != _dataRepository.end())	// 找到啦
	{
		MSG_VALUE&  msgValue = (*iter).second ; 

		msgValue.state = state;
		msgValue.timeWrite = std::chrono::high_resolution_clock::now();   // 获得当前时间

		MSG_VALUE::RECORD realData;
		realData.iDataLen = iDataLen;
		realData.pData = new char[realData.iDataLen];
		memset(realData.pData, 0, realData.iDataLen);

		memcpy(realData.pData, pData, realData.iDataLen);		// 赋值 

		msgValue.vecRecord.push_back(realData);		// 
	}
	else  // 没找到，直接新增
	{
		MSG_VALUE  msgValue;

		msgValue.state = state;
		msgValue.timeWrite = std::chrono::high_resolution_clock::now();   // 获得当前时间

		MSG_VALUE::RECORD realData;
		realData.iDataLen = iDataLen;
		realData.pData = new char[realData.iDataLen];
		memset(realData.pData, 0, realData.iDataLen);

		memcpy(realData.pData, pData, iDataLen);		// 赋值 

		msgValue.vecRecord.push_back(realData);		// 

		_dataRepository.insert(PAIR_DATA_REPOSITORY(iKey, msgValue));
	}

	return 0;
}

// 向数据仓库写入状态
int IDataRepository::setStateToRepository(int iMainCode, int iSubCode, int iT3Code, MSG_VALUE::STATE state)
{
	if (0 == _dataRepository.size())
		return ERR_dataRepository_size_is_0;

	int64_t  iKey = makeKey(iMainCode, iSubCode, iT3Code);

	std::lock_guard<std::recursive_mutex> guard(_lockRepository);		// 加锁

	MAP_DATA_REPOSITORY_ITER iter = _dataRepository.find(iKey);

	if (iter != _dataRepository.end())	// 找到啦
	{
		MSG_VALUE&  msgValue = (*iter).second;

		msgValue.state = state;
	}
	else  // 没找到
	{
		return  ERR_IS_NOT_FIND;
	}

	return 0;
}

/* --------------------------------------------------------------------------
函数说明：从数据仓库中读取数据
传入参数：
	iMainCode		主码
	iSubCode		辅助码
	iT3Code			三级码
	bClearMsgValueAfterRead		读取完数据后清除 MSG_VALUE 值 ，但 Key 并不移除，让这个 Key 下一次写入时还能用，毕竟查找 Key 要比 增加 Key 快得多
传出参
	msgValue		消息用到的【值】
返回值：
	成功则返回 0，失败返回错误码
-------------------------------------------------------------------------- */
int IDataRepository::readFromRepository(int iMainCode, int iSubCode, int iT3Code, MSG_VALUE& msgValue, bool bClearMsgValueAfterRead)
{
	if (0 == _dataRepository.size())
		return ERR_dataRepository_size_is_0;

	int64_t  iKey = makeKey(iMainCode, iSubCode, iT3Code);

	std::lock_guard<std::recursive_mutex> guard(_lockRepository);		// 加锁

	MAP_DATA_REPOSITORY_ITER iter = _dataRepository.find(iKey);

	if (iter != _dataRepository.end())	// 找到啦
	{
		MSG_VALUE&  tmp = (*iter).second;

		if (MSG_VALUE::DS_WRITE_FINISH == tmp.state)	// 状态为“已写完”才能读
		{
			msgValue.state = MSG_VALUE::DS_READ_FINISH;
			msgValue.timeRead = std::chrono::high_resolution_clock::now();   // 获得当前时间

			// 拷贝 vecRecord 中的数据给形参
			tmp.copyVecRecord(msgValue.vecRecord);

			if (bClearMsgValueAfterRead)	// 读取完数据后清除 MSG_VALUE 值
			{
				tmp.state = MSG_VALUE::DS_NO;		 // 数据状态
				memset(&tmp.timeWrite, 0, sizeof(tmp.timeWrite));  // 最后一次写入的时间
				memset(&tmp.timeRead, 0, sizeof(tmp.timeRead));

				tmp.releaseVecRecord();
			}
		}
		else
		{
			return ERR_IS_NOT_DS_WRITE_FINISH;
		}
	}
	else  // 没找到，直接新增
	{
		return ERR_dataRepository_size_is_0;
	}

	return 0;
}

/* --------------------------------------------------------------------------
函数说明：清空数据仓库中指定 Key 的 MSG_VALUE 值
传入参数：
	iMainCode		主码
	iSubCode		辅助码
	iT3Code			三级码
	bRemoveKey  true 表示移除Key ，即将容器内的 Key 和 MSG_VALUE 都移除。
	                          false 表示保留Key，但清除了 MSG_VALUE 中的记录值并初始化MSG_VALUE中的几个参数，
							            让这个 Key 下一次写入时还能用，毕竟查找 Key 要比 增加 Key 快得多，这样做是为了更高的效率。
返回值：
	成功则返回 0，失败返回错误码
-------------------------------------------------------------------------- */
int IDataRepository::clearFromRepository(int iMainCode, int iSubCode, int iT3Code, bool bRemoveKey)
{
	if (0 == _dataRepository.size())
		return ERR_dataRepository_size_is_0;

	int64_t  iKey = makeKey(iMainCode, iSubCode, iT3Code);

	std::lock_guard<std::recursive_mutex> guard(_lockRepository);		// 加锁

	MAP_DATA_REPOSITORY_ITER iter = _dataRepository.find(iKey);

	if (iter != _dataRepository.end())	// 找到啦
	{
		MSG_VALUE&  tmp = (*iter).second;

		tmp.state = MSG_VALUE::DS_NO;	// 无状态
		memset(&tmp.timeWrite, 0, sizeof(tmp.timeWrite));  // 最后一次写入的时间
		memset(&tmp.timeRead, 0, sizeof(tmp.timeRead));	// 最后一次读取的时间

		tmp.releaseVecRecord();	// 释放记录群

		if (bRemoveKey)	// 移除Key ，即将容器内的 Key 和 MSG_VALUE 都移除。
		{
			_dataRepository.erase(iter);	  
		}
	}
	else  // 没找到，直接新增
	{
		return ERR_dataRepository_size_is_0;
	}

	return 0;
}

// 清空数据仓库中所有的数据
int IDataRepository::clearAllData()
{
	if (0 == _dataRepository.size())
		return ERR_dataRepository_size_is_0;

	std::lock_guard<std::recursive_mutex> guard(_lockRepository);		// 加锁
	MAP_DATA_REPOSITORY_ITER  iter=_dataRepository.begin() ;

	while ((iter=_dataRepository.begin()) != _dataRepository.end())
	{
		MSG_VALUE&  tmp = (*iter).second;

		tmp.releaseVecRecord();	// 释放记录群

		_dataRepository.erase(iter);	// 移除
	}

	return 0;
}